在 PowerShell 中,資料不僅僅是文字、數字或符號,而是可以成為功能強大、富有結構的物件。物件化資料處理是 PowerShell 最為顯著的特點之一,它將資料轉化為具體的、有屬性和方法的物件,讓操作更加直觀、靈活且精確。
因此今天的重點在於幫助你理解物件的概念及其應用,為什麼在 PowerShell 中資料以物件的形式存在,能夠讓我們以全新的方式處理資料,並提高工作效率。
藉由深入理解物件的特性與運用,你將不僅僅是執行命令,而是能夠以面向物件的方式管理各種資料,這不僅有助於簡化日常管理任務,更能大幅提升腳本的可讀性與可維護性。因此,掌握物件是學習 PowerShell 的關鍵,這不僅是技術上的進階,更是對資料理解方式的根本性轉變。接下來,我們將探索物件的世界,揭開其背後的運作原理與強大之處。
物件是一種資料結構,它將資料與行為封裝在一起。具體來說,物件是來自於類別(Class)的實例,類別定義了物件的屬性和方法。屬性是描述物件特徵的變數,而方法是物件可以執行的操作或行為。
書中以 Get-Process
這個命令為例,當在終端機執行該指令時,你只會看到針對「處理程序」眾多資訊當中的極小部分,然後實際上每個處理程序物件( process object )都包含了機器名稱、主視窗控制碼( main windows handle )、最大工作集大小( maximum working set size )、結束代碼( exit code )等等超過 60 種相關的資訊,但是當你沒有特別為該命令指定你特別想看的欄位時,PowerShell 會參考 Microsoft 提供的設定檔後,只顯示 Microsoft 認為你想看的那些欄位。
有一個方法能查看所有的欄位,就是使用 ConvertTo-Html ,這個 cmdlet 不會篩選任何欄位。它會產生一個包含所有欄位的 HTML 檔案,這就是查看完整表格的一種方式。
PS /Users/kanglin/code/30days> Get-Process | ConvertTo-Html | Out-File getProcessHtml.html
PS /Users/kanglin/code/30days> ls -l
total 944
-rw-r--r--@ 1 kanglin staff 481558 9 23 12:51 getProcessHtml.html
當你下了一個可以產生輸出結果的命令時,該輸出命令會以「表格」的形式存於記憶體中,而當你透過 pipeline 將第一個命令的輸出結果傳遞給下一個命令時,該「表格」會完整被傳遞給下一個命令。
我會透過上面的 html table 截圖搭配書中所形容的術語做明顯標記,以便釐清。
PowerShell 不會把「儲存在記憶體的表格」稱為表格( table )。而是使用以下幾個特定名稱:
這是我們所說的表格中的一列( table row )。它代表一個實體,例如一個處理程序,或是一個儲存體帳戶( storage account )。
以下面截圖作為例子,red box 是一個物件,而一列就是一個獨立的物件,一個物件裡面會存放個別屬性的值。
這是我們所說的表格中的欄位( table column)。它代表一個物件的某項特定資訊,例如處理程序名稱、處理程序識別碼( process ID)、VM 的執行狀態( running status )等等。
以下面截圖作為例子,red box 物件的 SI 屬性值為 39406,green box 物件的 SI 屬性值為 297。
這是所有物件的整體組合,也就是我們之前所稱的表格。
物件化資料使得我們可以精確地獲取和操作資料的特定屬性,而不需要手動解析文字輸出。例如,我們可以直接存取一個程序物件的 CPU 屬性,而不必去分析命令的輸出文字。
透過物件的屬性和方法,我們可以用簡單且一致的方式操作各種不同類型的資料,無需編寫複雜的字串處理程式碼。
使用物件能讓腳本的語意更加清晰,使得腳本不僅易於撰寫和閱讀,也更容易進行維護和擴展。
透過 Get-Member
獲取物件的屬性與方法,僅需要在產生輸出結果的 cmdlet 後面透過 pipeline 將其結果( object )傳遞給 Get-Member
後,它便能存取該物件的所有屬性與方法後,在終端機畫面上列出物件所擁有的屬性與方法。
PS /Users/kanglin/code/30days> get-help Get-Member
NAME
Get-Member
SYNOPSIS
Gets the properties and methods of objects.
DESCRIPTION
The `Get-Member` cmdlet gets the members, the properties and methods, of objects.
To specify the object, use the InputObject parameter or pipe an object to `Get-Member`. To get information about static members, the members of the class, not of the instance, use the Static parameter. To get only certain types of members, such as NoteProperties, use the MemberType parameter.
`Get-Member` returns a list of members that's sorted alphabetically. Methods are listed first, followed by the properties.
執行 Get-Process
將處理程序物件放到管線中,接在管線後面的命令是 Sort-Object
,這個命令不會變更到管線中的Collection,僅是依據 Collection 裡的物件們將其做降序呈現,因此透過下個管線的 Get-Member
可得知其物件類型並未發生變化。
PS /Users/kanglin/code/30days> Get-Process | Sort-Object CPU -Descending | gm
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Handles AliasProperty Handles = Handlecount
Name AliasProperty Name = ProcessName
NPM AliasProperty NPM = NonpagedSystemMemorySize64
重覆剛剛的指令,但是在下個管線中,使用 Select-Object
時,它不會直接移除那些你不想保留的屬性,而是透過建立一個新型態的自訂物件,它透過處理程序中複製你想要的物件,最終生成一個型態為 Selected.System.Diagnostics.Process 的物件。
PS /Users/kanglin/code/30days> Get-Process | Sort-Object CPU -Descending | Select-Object Name,ID,CPU,SI | gm
TypeName: Selected.System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
預設升序,僅執行 Sort-Object
並指定對應的屬性即可,若要進行降序,則是加上 -Descending
的參數即可。
PS /Users/kanglin/code/30days> Get-Process | Sort-Object CPU -Descending | Select-Object -First 10
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
0 0.00 128.33 12,415.01 1059 1 Telegram
0 0.00 159.12 4,819.24 4014 1 Anytype Helper
0 0.00 153.47 4,805.44 55179 1 Google Chrome
0 0.00 23.62 4,497.21 31866 1 Notion Helper (
0 0.00 70.83 4,032.95 1309 1 iTerm2
0 0.00 75.95 3,207.82 31880 1 Notion Helper (
0 0.00 89.27 2,886.01 39440 …06 pwsh
0 0.00 41.16 2,661.18 55292 1 Google Chrome H
0 0.00 29.69 2,660.76 55228 1 Google Chrome H
0 0.00 62.00 2,303.03 4006 1 anytypeHelper
PS /Users/kanglin/code/30days> Get-Process | Sort-Object CPU | Select-Object -First 10
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
0 0.00 0.00 0.00 0 …06
0 0.00 0.00 0.00 1248 1
0 0.00 0.00 0.00 1354 …54
0 0.00 0.00 0.00 1355 …55
0 0.00 0.00 0.00 1838 …38
0 0.00 0.00 0.00 2188 …88
0 0.00 0.00 0.00 2315 …15
0 0.00 0.00 0.00 2324 1
0 0.00 0.00 0.00 2978 …78
0 0.00 0.00 0.00 4098 …98
先透過 Get-Member
確認目前物件所有的屬性( 截圖為部分結果 )
PS /Users/kanglin/code/30days> Get-Process | Get-Member -MemberType Property | Format-Table
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
BasePriority Property int BasePriority {get;}
Container Property System.ComponentModel.IContainer Container {get;}
EnableRaisingEvents Property bool EnableRaisingEvents {get;set;}
ExitCode Property int ExitCode {get;}
ExitTime Property datetime ExitTime {get;}
Handle Property System.IntPtr Handle {get;}
HandleCount Property int HandleCount {get;}
HasExited Property bool HasExited {get;}
Id Property int Id {get;}
MachineName Property string MachineName {get;}
MainModule Property System.Diagnostics.ProcessModule MainModule {get;}
接著便可以透過 Select-Object
選擇你想要的屬性,另外可透過 -First
或 -Last
呈現最初或最後的筆數。
PS /Users/kanglin/code/30days> Get-Process | Select-Object -Property ProcessName,Threads,Id,Handle -Last 5
ProcessName Threads Id Handle
----------- ------- -- ------
WeatherWidget {103387168, 1804136672, 1804710112, 1805283552…} 17726 7164
WiFiAgent {103387168, 1804431584, 1805005024, 1800417504…} 687 1072
WindowManager {103387168, 1870328032, 1871474912, 1868034272} 590 6328
WorldClockWidge {103387168, 1873653984, 1874227424, 1874800864} 17727 6372
zsh {103387168} 39407 7112
PS /Users/kanglin/code/30days> Get-Process | Select-Object -Property ProcessName,Threads,Id,Handle -First 5
ProcessName Threads Id Handle
----------- ------- -- ------
{} 0 5176
{} 1 2580
{} 297 4276
{} 299 4484
{} 301 5368
Day 10 - 深度探索管線